#include <math.h>
#include <string.h>
#include <stdlib.h>
#include "hashlib.h"
#include "li_collections.h"
#include "li_basic.h"
#include "li_vars.h"
#include "cre.h"
#include "ca_config.h"

#pragma region macro
//#define SearchIn(T){\
//	int32_t i, n;\
//	n = _##T->count;\
//	T ts = (T)(_##T->content);\
//	uint32_t hc1 = getHashCodeS(item);\
//	for (i = 0; i < n; i++){\
//		if (hc1 != ts[i].hashCode)\
//			continue;\
//		if (!strcmp(item, ts[i].name))\
//			return i;\
//	}\
//	return -1;\
//}

#define SearchIn2(T)                                        \
	int32_t search##T(const Li_List _##T, const char *item) \
	{                                                       \
		int32_t i, n;                                       \
		n = _##T->count;                                    \
		T ts = (T)(_##T->content);                          \
		uint32_t hc1 = getHashCodeS(item);                  \
		for (i = 0; i < n; i++)                             \
		{                                                   \
			if (hc1 != ts[i].hashCode)                      \
				continue;                                   \
			if (!strcmp(item, ts[i].name))                  \
				return i;                                   \
		}                                                   \
		return -1;                                          \
	}

#define AddTo(T)                                         \
	int32_t addTo##T(const Li_List _##T, T new_cmd)      \
	{                                                    \
		new_cmd->hashCode = getHashCodeS(new_cmd->name); \
		return list_add(_##T, new_cmd);                  \
	}

#define RemoveFrom(T)                                        \
	int32_t removeFrom##T(const Li_List _##T, int32_t index) \
	{                                                        \
		return list_remove_at(_##T, index);                  \
	}

#define RemoveFrom2(T)                                                   \
	int32_t removeFrom##T##_by_str(const Li_List _##T, const char *name) \
	{                                                                    \
		int32_t index = search##T(_##T, name);                           \
		if (index < 0)                                                   \
			return -1;                                                   \
		return removeFrom##T(_##T, index);                               \
	}
#pragma endregion

int32_t addObj(const Li_List list, Object obj)
{
	obj->hashCode = getHashCodeS(obj->name);
	return list_add(list, obj);
}
int32_t searchObj(const Li_List li, const char *name)
{
	if (!li)
		return -1;
	int32_t i, n;
	n = li->count;
	Object ts = (Object)(li->content);
	uint32_t hc1 = getHashCodeS(name);
	for (i = n - 1; i >= 0; i--)
	{
		if (hc1 != ts[i].hashCode)
			continue;
		if (!strcmp(name, ts[i].name))
			return i;
	}
	return -1;
}
int32_t searchObj2(const Li_List li, const char *name, uint32_t hc)
{
	if (!li)
		return -1;
	int32_t i, n;
	n = li->count;
	Object ts = (Object)(li->content);
	for (i = n - 1; i >= 0; i--)
	{
		if (hc != ts[i].hashCode)
			continue;
		if (!strcmp(name, ts[i].name))
			return i;
	}
	return -1;
}
int32_t searchObj3(const Li_List li, uint32_t hc)
{
	if (!li)
		return -1;
	int32_t i, n;
	n = li->count;
	Object ts = (Object)(li->content);
	for (i = n - 1; i >= 0; i--)
	{
		if (hc == ts[i].hashCode)
			return i;
	}
	return -1;
}

int32_t searchObj_t(const Li_List li, const char *name)
{
	if (!li)
		return -1;
	int32_t i, n;
	n = li->count - 1;
	uint32_t hc1 = getHashCodeS(name);
	int8_t *bs = li->content;
	bs += li->type_size * n;
	for (i = n; i >= 0; i--, bs -= li->type_size)
	{
		if (hc1 != ((Object)bs)->hashCode)
			continue;
		if (!strcmp(name, ((Object)bs)->name))
			return i;
	}
	return -1;
}
int32_t searchObj2_t(const Li_List li, const char *name, uint32_t hc)
{
	if (!li)
		return -1;
	int32_t i, n;
	n = li->count - 1;
	int8_t *bs = li->content;
	bs += li->type_size * n;
	for (i = n; i >= 0; i--, bs -= li->type_size)
	{
		if (hc != ((Object)bs)->hashCode)
			if (!strcmp(name, ((Object)bs)->name))
				return i;
	}
	return -1;
}
int32_t searchObj3_t(const Li_List li, uint32_t hc)
{
	if (!li)
		return -1;
	int32_t i, n;
	n = li->count - 1;
	int8_t *bs = li->content;
	bs += li->type_size * n;
	for (i = n; i >= 0; i--, bs -= li->type_size)
	{
		if (hc == ((Object)bs)->hashCode)
			return i;
	}
	return -1;
}

int32_t searchCmd(const Li_List _Cmd, const char *item);
int32_t searchFun(const Li_List _Fun, const char *item);
int32_t searchVar(const Li_List _Var, const char *item);

SearchIn2(Fun);
SearchIn2(Cmd);
SearchIn2(Var);

AddTo(Cmd);
RemoveFrom(Cmd);
RemoveFrom2(Cmd);

AddTo(Fun);
RemoveFrom(Fun);
RemoveFrom2(Fun);

AddTo(Var);
RemoveFrom(Var);
RemoveFrom2(Var);

#pragma region CMD

#undef vvar
#pragma endregion
